<?php

// +----------------------------------------------------------------------
// | H1CMS © OpenSource CMS
// +----------------------------------------------------------------------
// | Copyright (c) 2014-2016 http://www.h1cms.com All rights reserved.
// | Copyright (c) 2014-2016 嘉兴领格信息技术有限公司，并保留所有权利。
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Allen <allen@lg4.cn>
// +----------------------------------------------------------------------

namespace Lg\View;

use Closure;
use ArrayAccess;
use Lg\Traits\ArrayTrait;
use Lg\Traits\DataAttrTrait;

/**
 * Description of View
 *
 * @author getssl
 */
class View implements ArrayAccess {

    use ArrayTrait;

use DataAttrTrait;

    /**
     *
     * @var string template name
     */
    protected $name;

    /**
     *
     * @var Lg\View\Engine|\Lg\View\Engines\SmartyEngine|\Lg\View\Engines\PhpEngine 模板引擎
     */
    protected $engine;
    protected $debug = false;

    /**
     *
     * @var string template path
     */
    protected $path;
    protected $tplPath;
    protected $engineName = 'php';
    protected static $_view;

    public function __construct($name, $data = array()) {
        $this->name = $name;
        $this->data = $data instanceof Closure ? [] : $data;
        if (defined('THEMES_PATH')) {
            $this->path = THEMES_PATH . get_option('system.theme', 'basic');
        } else {
            $this->path = module_path('views');
        }
        if (!strncmp($name, '@', 1)) {
            $pos = strpos($name, '/');
            $root = $pos === false ? $name : substr($name, 0, $pos);
            $this->path = dirname(\LG::getAlias($name));
            $this->name = basename($name);
        }
        $this->prepare();
    }

    protected function prepare() {
        if (is_file($this->path . DS . $this->name . '.php')) {
            $this->engine = static::getEngine('php');
            $this->tplPath = $this->path . DS . $this->name . '.php';
        } else if (is_file($this->path . DS . $this->name . '.smarty.php')) {
            $this->engine = static::getEngine('smarty');
            $this->engine->setTemplateDir($this->path);
            $this->tplPath = $this->path . DS . $this->name . '.smarty.php';
        } else {
            throw new \Exception('Template ' . $this->name . ' not found');
        }
    }

    public function getTemplateName($name) {
        if (is_file($this->path . DIRECTORY_SEPARATOR . $name . '.php')) {
            return $this->path . DIRECTORY_SEPARATOR . $name . '.php';
        } else if (is_file($this->path . DIRECTORY_SEPARATOR . $name . '.smarty.php')) {
            return $this->path . DIRECTORY_SEPARATOR . $name . '.smarty.php';
        }
        return NULL;
    }

    public static function capsule($name, $data = array()) {
        $view = new View($name, $data);
        if ($data instanceof Closure) {
            $data($view);
        }
        return $view;
    }
    /**
     * 
     * @param string $name
     * @param Closure $data
     * @return \Lg\View\View
     */
    public static function make($name, $data = array()) {
        if (is_null(static::$_view)) {
            static::$_view = new View($name, $data);
        } else {
            return static::capsule($name, is_array($data) ? array_merge(static::$_view->getData(), $data) : $data);
        }
        if ($data instanceof Closure) {
            $data(static::$_view);
        }
        return static::$_view;
    }

    public static function block($name, $data = array()) {
        if (is_null(static::$_view)) {
            static::$_view = new View($name, $data);
        }
        return static::capsule($name, $data);
    }

    public function with($key, $value = null) {
        if (is_array($key)) {
            $this->data = array_merge($this->data, $key);
        } else {
            $this->data[$key] = $value;
        }
        return $this;
    }

    public function debug() {
        $this->debug = true;
        return $this;
    }

    public function getData() {
        return $this->data;
    }

    public function setData($key, $value = null) {
        return $this->with($key, $value);
    }

    public function getPath() {
        return $this->path;
    }

    public function setPath($path) {
        $this->path = $path;
    }

    public function getTplPath() {
        return $this->tplPath;
    }

    public function render($data = [], $return_output = false) {
        $this->engine->debug = $this->debug;
        $this->setData($data);
        return $this->engine->render($this->tplPath, $this->data, $return_output);
    }

    public function layout($name, $return_output = true) {
        return $this->engine->render($this->tplPath, $this->data, $return_output);
    }

    public function __toString() {
        return $this->render($this->data, true);
    }

    /**
     *      
     * @return Engines\PhpEngine|Engines\SmartyEngine
     */
    public function engine() {
        return $this->engine;
    }

    public static function getEngine($name = 'php') {
        if ($name == 'php') {
            $engine = \Lg\Container::getInstance()->get('phpEngine');
            if (is_null($engine)) {
                $engine = new Engines\PhpEngine();
            }
            \Lg\Container::getInstance()->set('phpEngine', $engine);
            return $engine;
        } else if ($name == 'smarty') {
            $engine = \Lg\Container::getInstance()->get('smartyEngine');
            if (is_null($engine)) {
                $engine = new Engines\SmartyEngine();
                $engine->addPluginsDir(SYSTEM_DIR . 'thirdparty/smarty/plugins');
                if (defined('LG_ADMIN')) {
                    $engine->addPluginsDir(module_path('views/plugins'));
                }
                $engine->addConfigDir(SYSTEM_DIR . 'thirdparty/smarty/configs');
                $engine->addConfigDir(CONFIG_DIR . 'smarty_configs');
                $engine->allow_php_templates = true;
                $engine->setCompileDir(STORAGE_DIR . 'templates_c/' . value_condition(defined('LG_ADMIN'), 'admin'));
                $engine->setCacheDir(CACHE_DIR . 'smarty');
            }
            \Lg\Container::getInstance()->set('smartyEngine', $engine);
            return $engine;
        }
    }

}
